package models

import (
	"context"
	"github.com/ethereum/go-ethereum/common"
	"go-chain-api/global"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"gorm.io/gorm"
	"log"
	"regexp"
)

// TokenInfo 结构体对应JSON对象
type TokenInfo struct {
	Id          string `bson:"_id,omitempty" json:"id"`
	ChainName   string `bson:"chainName" json:"chainName"`
	ChainID     int64  `bson:"chainId" json:"chainId"`
	Address     string `bson:"address" json:"address"`
	Name        string `bson:"name" json:"name"`
	Symbol      string `bson:"symbol" json:"symbol"`
	Decimals    uint   `bson:"decimals" json:"decimals"`
	TotalSupply string `bson:"totalSupply" json:"totalSupply"`
	IsErc20     string `bson:"isErc20" json:"isErc20"`
}

type MysqlToken struct {
	gorm.Model
	ChainId        uint   `gorm:"not null"`
	Address        string `gorm:"type:varchar(42);unique_index"` // 合约地址，Ethereum地址长度为42个字符
	Creator        string `gorm:"type:varchar(42)"`              // 创建者地址
	Name           string `gorm:"type:varchar(42)"`              //名称
	Symbol         string `gorm:"type:varchar(66)"`              //符号
	Decimals       uint8  `gorm:""`                              //精度
	TotalSupply    string `gorm:""`                              //总发行量
	Price          string `gorm:"type:varchar(66)"`              //价格
	CreationTxHash string `gorm:"type:varchar(66);unique_index"` // 创建合约的交易哈希，哈希长度为66个字符
	BlockNumber    uint64 `gorm:"type:bigint"`                   // 创建合约时的区块号
	Timestamp      uint64 `gorm:""`                              // 创建合约的时间戳
	ABI            string `gorm:"type:text"`                     // 合约的ABI（Application Binary Interface）
	Verified       bool   `gorm:"type:boolean"`                  // 合约是否已验证
	IsScan         bool   `gorm:"type:boolean"`                  //是否要扫描这个token
	IsErc20        bool   `gorm:"type:boolean"`                  //是否要扫描这个代币的交易
	Amplitude      string `gorm:"-"`                             //涨跌
	Transaction24  string `gorm:"-"`                             //24小时交易量
	Hold           int64  `gorm:"-"`                             //持有人
}

// GetTokenInfoByAddress 根据地址获取代币信息
func (token TokenInfo) GetTokenInfoByAddress(address string) *TokenInfo {
	var tokenInfo *TokenInfo
	BlocksClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("token")
	err := BlocksClient.FindOne(context.Background(), bson.D{{"address", common.HexToAddress(address).Hex()}}).Decode(&tokenInfo)
	if err != nil {
		log.Println("failed to token address:", err)
	}
	return tokenInfo
}

// AddToken 添加代币
func (token TokenInfo) AddToken() error {
	BlocksClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("token")
	_, err := BlocksClient.InsertOne(context.Background(), token)
	if err != nil {
		return err
	}
	return nil
}

// GetTokenList 获取代币列表
func (token TokenInfo) GetTokenList(chainName string, chainId uint) ([]*TokenInfo, error) {
	var tokenList []*TokenInfo
	BlocksClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("token")
	addressRegex := bson.M{"$regex": primitive.Regex{Pattern: `^.{42}$`, Options: ""}}
	filter := bson.D{{"chainName", chainName}, {"chainId", chainId}, {"address", addressRegex}}
	cursor, err := BlocksClient.Find(context.Background(), filter)
	if err != nil {
		return nil, err
	}
	err = cursor.All(context.Background(), &tokenList)
	if err != nil {
		return nil, err
	}
	return tokenList, nil
}

func IsValidEthereumAddress(addr string) bool {
	// 正则表达式匹配0x开头的42个字符，其中后面40个字符是十六进制数
	re := regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
	return re.MatchString(addr)
}

func IsValidTrxAddress(addr string) bool {
	// TRX地址是34个字符长，只包含大写字母和数字
	re := regexp.MustCompile("^[A-Z0-9]{34}$")
	return re.MatchString(addr)
}

func GetMainToken(address string) *TokenInfo {
	var tokenInfo *TokenInfo
	BlocksClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("token")
	err := BlocksClient.FindOne(context.Background(), bson.D{{"address", address}}).Decode(&tokenInfo)
	if err != nil {
		log.Println("failed to token address:", err)
	}
	return tokenInfo
}
